// Copyright 2019 The FlutterCandies author. All rights reserved.
// Use of this source code is governed by an Apache license that can be found
// in the LICENSE file.

import 'dart:io';

import 'package:extended_image/extended_image.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:photo_manager/photo_manager.dart';
import 'package:photo_manager_image_provider/photo_manager_image_provider.dart';
import 'package:video_player/video_player.dart';
import 'package:visibility_detector/visibility_detector.dart';
import 'package:wechat_picker_library/wechat_picker_library.dart';

import '../../constants/constants.dart';
import '../../delegates/asset_picker_text_delegate.dart';
import '../../delegates/asset_picker_viewer_builder_delegate.dart';
import 'ohos_asset_image_provider.dart';
import 'package:photo_manager/platform_utils.dart';

class ImagePageBuilder extends StatefulWidget {
  const ImagePageBuilder({
    super.key,
    required this.asset,
    required this.delegate,
    this.previewThumbnailSize,
    this.shouldAutoplayPreview = false,
  });

  /// Asset currently displayed.
  /// 展示的资源
  final AssetEntity asset;

  final AssetPickerViewerBuilderDelegate<AssetEntity, AssetPathEntity> delegate;

  final ThumbnailSize? previewThumbnailSize;

  /// Whether the preview should auto play.
  /// 预览是否自动播放
  final bool shouldAutoplayPreview;

  @override
  State<ImagePageBuilder> createState() => _ImagePageBuilderState();
}

class _ImagePageBuilderState extends State<ImagePageBuilder> {
  bool _isLocallyAvailable = false;
  VideoPlayerController? _livePhotoVideoController;

  bool get _isOriginal => widget.previewThumbnailSize == null;

  bool get _isLivePhoto => widget.asset.isLivePhoto;

  @override
  void didUpdateWidget(ImagePageBuilder oldWidget) {
    super.didUpdateWidget(oldWidget);
    if (widget.asset != oldWidget.asset ||
        widget.previewThumbnailSize != oldWidget.previewThumbnailSize) {
      _isLocallyAvailable = false;
      _livePhotoVideoController
        ?..pause()
        ..dispose();
      _livePhotoVideoController = null;
    }
  }

  @override
  void dispose() {
    _livePhotoVideoController?.dispose();
    super.dispose();
  }

  Future<void> _initializeLivePhoto() async {
    final File? file;
    if (_isOriginal) {
      file = await widget.asset.originFileWithSubtype;
    } else {
      file = await widget.asset.fileWithSubtype;
    }
    if (!mounted || file == null) {
      return;
    }
    final VideoPlayerController c = VideoPlayerController.file(
      file,
      videoPlayerOptions: VideoPlayerOptions(mixWithOthers: true),
    );
    await c.initialize();
    safeSetState(() {
      _livePhotoVideoController = c;
    });
    c.addListener(() {
      safeSetState(() {});
    });
  }

  Widget _imageBuilder(BuildContext context, AssetEntity asset) {
    // 鸿蒙平台特殊处理，确保预览时显示原图
    if (PlatformUtils.isOhos) {
      // 鸿蒙平台使用自定义的图片提供者
      final ImageProvider imageProvider = OhosAssetEntityImageProvider(
        asset,
        isOriginal: _isOriginal,
        thumbnailSize: widget.previewThumbnailSize,
      );
      
      return ExtendedImage(
        image: imageProvider,
        fit: BoxFit.contain,
        mode: ExtendedImageMode.gesture,
        onDoubleTap: widget.delegate.updateAnimation,
        initGestureConfigHandler: (ExtendedImageState state) => GestureConfig(
          minScale: 1.0,
          maxScale: 3.0,
          animationMinScale: 0.6,
          animationMaxScale: 4.0,
          inPageView: true,
          initialAlignment: InitialAlignment.center,
        ),
        loadStateChanged: (ExtendedImageState state) {
          final imageWidget = widget.delegate.previewWidgetLoadStateChanged(
            context,
            state,
            hasLoaded: state.extendedImageLoadState == LoadState.completed,
          );
          if (_isLivePhoto && _livePhotoVideoController != null) {
            return _LivePhotoWidget(
              controller: _livePhotoVideoController!,
              fit: BoxFit.contain,
              state: state,
              textDelegate: widget.delegate.textDelegate,
            );
          }
          return imageWidget;
        },
      );
    } else {
      // 安卓和其他平台使用原始逻辑
      return ExtendedImage(
        image: AssetEntityImageProvider(
          asset,
          isOriginal: _isOriginal,
          thumbnailSize: widget.previewThumbnailSize,
        ),
        fit: BoxFit.contain,
        mode: ExtendedImageMode.gesture,
        onDoubleTap: widget.delegate.updateAnimation,
        initGestureConfigHandler: (ExtendedImageState state) => GestureConfig(
          minScale: 1.0,
          maxScale: 3.0,
          animationMinScale: 0.6,
          animationMaxScale: 4.0,
          inPageView: true,
          initialAlignment: InitialAlignment.center,
        ),
        loadStateChanged: (ExtendedImageState state) {
          final imageWidget = widget.delegate.previewWidgetLoadStateChanged(
            context,
            state,
            hasLoaded: state.extendedImageLoadState == LoadState.completed,
          );
          if (_isLivePhoto && _livePhotoVideoController != null) {
            return _LivePhotoWidget(
              controller: _livePhotoVideoController!,
              fit: BoxFit.contain,
              state: state,
              textDelegate: widget.delegate.textDelegate,
            );
          }
          return imageWidget;
        },
      );
    }
  }

  @override
  Widget build(BuildContext context) {
    return LocallyAvailableBuilder(
      key: ValueKey<String>(widget.asset.id),
      asset: widget.asset,
      isOriginal: _isOriginal,
      withSubtype: _isOriginal,
      thumbnailOption: switch (widget.previewThumbnailSize) {
        final size? => ThumbnailOption(size: size),
        _ => null,
      },
      builder: (BuildContext context, AssetEntity asset) {
        // Initialize the video controller when the asset is a Live photo
        // and available for further use.
        if (!_isLocallyAvailable && _isLivePhoto) {
          _initializeLivePhoto();
        }
        _isLocallyAvailable = true;
        return GestureDetector(
          behavior: HitTestBehavior.opaque,
          onTap: widget.delegate.switchDisplayingDetail,
          child: _imageBuilder(context, asset),
        );
      },
    );
  }
}

class _LivePhotoWidget extends StatefulWidget {
  const _LivePhotoWidget({
    required this.controller,
    required this.state,
    required this.fit,
    required this.textDelegate,
  });

  final VideoPlayerController controller;
  final ExtendedImageState state;
  final BoxFit fit;
  final AssetPickerTextDelegate textDelegate;

  @override
  State<_LivePhotoWidget> createState() => _LivePhotoWidgetState();
}

class _LivePhotoWidgetState extends State<_LivePhotoWidget> {
  final _showVideo = ValueNotifier<bool>(false);
  late final _controller = widget.controller;

  ScrollNotificationObserverState? _scrollNotificationObserver;
  bool _scrolling = false;

  @override
  void initState() {
    super.initState();
    _controller.addListener(_notify);
  }

  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
    _scrollNotificationObserver?.removeListener(_handleScrollNotification);
    _scrollNotificationObserver = ScrollNotificationObserver.maybeOf(context);
    _scrollNotificationObserver?.addListener(_handleScrollNotification);
  }

  @override
  void dispose() {
    _scrollNotificationObserver?.removeListener(_handleScrollNotification);
    _controller.removeListener(_notify);
    _showVideo.dispose();
    super.dispose();
  }

  void _notify() {
    if (_controller.value.isPlaying != _showVideo.value) {
      _showVideo.value = _controller.value.isPlaying;
    }
  }

  void _handleScrollNotification(ScrollNotification notification) {
    if (notification is ScrollStartNotification && notification.dragDetails != null) {
      _scrolling = true;
    } else if (notification is ScrollEndNotification) {
      _scrolling = false;
    }
  }

  @override
  Widget build(BuildContext context) {
    return VisibilityDetector(
      key: ObjectKey(widget.controller),
      onVisibilityChanged: (VisibilityInfo info) {
        if (info.visibleFraction == 0 && _controller.value.isPlaying) {
          _controller.pause();
        }
      },
      child: ExtendedImageGesture(
        widget.state,
        imageBuilder: (
          Widget image, {
          ExtendedImageGestureState? imageGestureState,
        }) {
          return ValueListenableBuilder<bool>(
            valueListenable: _showVideo,
            builder: (BuildContext context, bool showVideo, Widget? child) {
              return Stack(
                fit: StackFit.expand,
                children: <Widget>[
                  image, // 使用传入的image参数
                  if (showVideo)
                    Positioned.fill(
                      child: FittedBox(
                        fit: widget.fit,
                        child: SizedBox(
                          width: _controller.value.size.width,
                          height: _controller.value.size.height,
                          child: VideoPlayer(_controller),
                        ),
                      ),
                    ),
                  if (!_scrolling && imageGestureState != null)
                    Positioned.fill(
                      child: GestureDetector(
                        behavior: HitTestBehavior.opaque,
                        onTap: () {
                          if (_controller.value.isPlaying) {
                            _controller.pause();
                          } else {
                            if (!_controller.value.isInitialized) {
                              return;
                            }
                            _controller.play();
                          }
                        },
                        onDoubleTap: () {
                          // 现在我们可以正确地调用handleDoubleTap方法了
                          imageGestureState.handleDoubleTap();
                        },
                      ),
                    ),
                  if (!showVideo)
                    Positioned(
                      top: 8.0,
                      right: 8.0,
                      child: Container(
                        width: 25.0,
                        height: 25.0,
                        decoration: const BoxDecoration(
                          shape: BoxShape.circle,
                          color: Colors.black54,
                        ),
                        child: Center(
                          child: Icon(
                            Icons.live_tv,
                            color: Colors.white,
                            size: 18.0,
                          ),
                        ),
                      ),
                    ),
                ],
              );
            },
          );
        },
      ),
    );
  }
}